<template>
  <div>
    <div class="cropper-content">
      <div class="cropper">
        <VueCropper
          ref="cropper"
          :img="option.img"
          :output-size="option.outputSize"
          :output-type="option.outputType"
          :info="true"
          :info-true="true"
          :full="option.full"
          :can-move="option.canMove"
          :can-move-box="option.canMoveBox"
          :original="option.original"
          :auto-crop="option.autoCrop"
          :auto-crop-width="option.autoCropWidth"
          :auto-crop-height="option.autoCropHeight"
          :fixed-box="option.fixedBox"
          :center-box="option.centerBox"
          :fixed="option.fixed"
          :fixed-number="option.fixedNumber"
          @realTime="realTime"
        />
      </div>
      <div style="height: 300px;">
        <span class="m-b-10">预览</span>
        <div ref="preview_circular" class="show-preview" :style="{'width': '130px', 'height': '100px', 'margin': '30px 0 20px 0'}">
          <div :style="previewCircularFileStyle">
            <img :src="previews.url" :style="previews.img">
          </div>
        </div>
        <div class="show-preview" :style="{'width': '130px', 'height': '130px'}">
          <div :style="previewSquareFileStyle">
            <img :src="previews.url" :style="previews.img">
          </div>
        </div>
      </div>
    </div>
    <div class="footer-btn">
      <div class="scope-btn">
        <label class="btn">
          <input id="uploads" ref="uploads" type="file" style="position:absolute; clip:rect(0 0 0 0);" accept="image/*" @change="changeImg($event)">
          更换图片
        </label>

        <el-button type="primary" icon="el-icon-zoom-in" circle @click="scale(1)" />
        <el-button type="primary" icon="el-icon-zoom-out" circle @click="scale(-1)" />
        <el-button type="primary" icon="el-icon-refresh-left" circle @click="rotate(-15)" />
        <el-button type="primary" icon="el-icon-refresh-right" circle @click="rotate(15)" />
      </div>
      <div class="upload-btn">
        <el-button type="info" @click="onReset">重 置</el-button>
        <el-button type="primary" @click="onUpload">保 存</el-button>
      </div>
    </div>
  </div>
</template>

<script>
import { VueCropper } from 'vue-cropper'

export default {
  name: 'ImageCropper',
  components: {
    VueCropper
  },
  props: {
    fixedSize: {
      type: Boolean,
      default: true
    },
    uploadUrl: {
      type: String,
      default: `${process.env.VUE_APP_MODULE_ADMIN_API}/api/system/user/uploadAvatar`
    },
    fileParam: {
      type: String,
      default: 'avatar_file'
    },
    cropperParam: {
      type: String,
      default: 'avatar_data'
    }
  },
  data() {
    return {
      option: {
        img: '',        // 裁切图片的地址
        outputSize: 1,  // 裁剪生成图片的质量 0.1-1
        full: false,    // 是否输出原图比例的截图
        outputType: 'png', // 裁剪生成图片的格式
        canMove: true,     // 图片是否允许滚轮缩放
        fixedBox: false,   // 固定截图框大小 不允许改变
        original: false,   // 上传图片按照原始比例渲染
        canMoveBox: true,  // 截图框能否拖动
        autoCropWidth: 150,
        autoCropHeight: 150,
        autoCrop: true,   // 是否默认生成截图框
        fixed: false,     // 开启宽度和高度比例
        fixedNumber: [1, 1],
        centerBox: true
      },
      previews: {},
      previewCircularFileStyle: {},
      previewSquareFileStyle: {}
    }
  },
  mounted() {
    this.option.fixed = this.fixedSize
    if (!this.option.fixed) {
      this.option.fixedNumber = []
      this.$refs.preview_circular.style.display = 'none'
    } else {
      this.$refs.preview_circular.style.display = ''
    }
  },
  methods: {
    init(imgUrl) {
      this.option.img = imgUrl
    },
    realTime(data) {
      this.previews = data
      let scale = 100 / data.w
      if (this.option.fixed) {
        this.previewCircularFileStyle = {
          width: data.w + 'px',
          height: data.h + 'px',
          margin: 0,
          overflow: 'hidden',
          zoom: scale,
          position: 'relative',
          border: '1px solid #e8e8e8',
          'border-radius': '50%'
        }
      }
      scale = 120 / data.w
      this.previewSquareFileStyle = {
        width: data.w + 'px',
        height: data.h + 'px',
        margin: 0,
        overflow: 'hidden',
        zoom: scale,
        position: 'relative',
        border: '1px solid #e8e8e8',
        'border-radius': '2px'
      }
    },
    changeImg(e) {
      // 上传图片
      const file = e.target.files[0]
      if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
        this.$modal.msgWarning('图片类型必须是gif,jpeg,jpg,png,bmp')
        return false
      }

      const reader = new FileReader()
      reader.onload = (e) => {
        let data
        if (typeof e.target.result === 'object') {
          // 把Array Buffer转化为blob 如果是base64不需要
          data = window.URL.createObjectURL(new Blob([e.target.result]))
        } else {
          data = e.target.result
        }

        this.option.img = data
      }
      // 转化为base64
      // reader.readAsDataURL(file)
      // 转化为blob
      reader.readAsArrayBuffer(file)
    },
    scale(num) {
      num = num || 1
      this.$refs.cropper.changeScale(num)
    },
    rotate(num) {
      if (num < 0) {
        this.$refs.cropper.rotateLeft()
      } else {
        this.$refs.cropper.rotateRight()
      }
    },
    onUpload() {
      // 获取cropper的截图的base64 数据
      this.$refs.cropper.getCropBlob(data => {
        // 将剪裁后base64的图片转化为file格式
        const originFile = this.$refs.uploads.files[0]
        if (!originFile) {
          this.$modal.msgError('请选择图片')
          return
        }

        // 将剪裁后的图片执行上传
        const formData = new FormData()
        formData.append(this.fileParam, data, originFile.name)
        this.$http({
          url: this.uploadUrl,
          method: 'post',
          cache: false,
          data: formData,
          processData: false,
          contentType: false
        }).then(response => {
          this.$modal.msgSuccess(response.msg)
          this.$refs.uploads.value = ''
          this.$emit('onSuccess', response.param)
        }).catch(() => {})
      })
    },
    onUploadOrigin() {
      const file = this.$refs.uploads.files[0]
      if (!file) {
        this.$modal.msgWarning('请选择图片')
        return
      }

      const json = [
        '{"x":' + this.$refs.cropper.cropOffsertX / this.$refs.cropper.scale,
        '"y":' + this.$refs.cropper.cropOffsertY / this.$refs.cropper.scale,
        '"height":' + this.$refs.cropper.w / this.$refs.cropper.scale,
        '"width":' + this.$refs.cropper.h / this.$refs.cropper.scale,
        // '"height":' + this.$refs.cropper.trueHeight,
        // '"width":' + this.$refs.cropper.trueWidth,
        '"rotate":' + this.$refs.cropper.rotate + '}'
      ].join()

      const data = new FormData()
      data.append(this.fileParam, file)
      data.append(this.cropperParam, json)
      this.$http({
        url: this.uploadUrl,
        method: 'post',
        cache: false,
        data: data,
        processData: false,
        contentType: false
      }).then(response => {
        this.$modal.msgSuccess(response.msg)
        this.$refs.uploads.value = ''
        this.$emit('onSuccess', response.param)
      }).catch(() => {})
    },
    onReset() {
      this.$refs.uploads.value = ''
      this.option.img = ''
    }
  }
}
</script>

<style lang="scss" scoped>
.cropper-content {
  display: flex;
  display: -webkit-flex;
  justify-content: flex-end;
  -webkit-justify-content: flex-end;
  .cropper {
    width: calc(100vw - 150px);
    height: 300px;
    margin-right: 20px;
  }
  .show-preview {
    flex: 1;
    -webkit-flex: 1;
    display: flex;
    display: -webkit-flex;
    justify-content: center;
    -webkit-justify-content: center;
  }
}
.footer-btn {
  padding: 10px 0 10px 0;
  display: flex;
  display: -webkit-flex;
  justify-content: flex-end;
  -webkit-justify-content: flex-end;
  .scope-btn {
    width: 350px;
    display: flex;
    display: -webkit-flex;
    justify-content: space-between;
    -webkit-justify-content: space-between;
  }
  .upload-btn {
    flex: 1;
    -webkit-flex: 1;
    display: flex;
    display: -webkit-flex;
    justify-content: center;
    -webkit-justify-content: center;
  }
  .btn {
    outline: none;
    display: inline-block;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    -webkit-appearance: none;
    text-align: center;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    outline: 0;
    margin: 0;
    -webkit-transition: .1s;
    transition: .1s;
    font-weight: 500;
    padding: 8px 15px;
    font-size: 12px;
    border-radius: 3px;
    color: #fff;
    background-color: #67c23a;
    border-color: #67c23a;
  }
}
</style>
